package me.aartikov.alligator;


import me.aartikov.alligator.animations.AnimationData;

import java.util.List;

/**
 * Interface with navigation methods.
 */
public interface Navigator {

    /**
     * Returns if a navigator can execute a command immediately
     *
     * @return true if a navigator can execute a command immediately
     */

    boolean canExecuteCommandImmediately();

    /**
     * Returns if a navigator has pending commands
     *
     * @return true if a navigator has pending commands
     */
    boolean hasPendingCommands();

    /**
     * Adds a new screen and goes to it.
     *
     * @param screen new screen
     */
    void goForward(Screen screen);

    /**
     * {@code goForward} with an animation data.
     *
     * @param screen        new screen
     * @param animationData animation data for an additional animation configuring
     */
    void goForward(Screen screen, AnimationData animationData);


    /**
     * Finishes a current screen and goes back to the previous screen.
     *
     * @return whether succeed
     */
    boolean goBack();


    /**
     * {@code goBack} with an animation data.
     *
     * @param screen        page bind data
     * @param animationData animationData animation data for an additional animation configuring
     * @return whether succeed
     */
    boolean goBack(Screen screen, AnimationData animationData);

    /**
     * Finishes a current screen and goes back to the previous screen with result.
     *
     * @param screenResult screen result that will be returned
     * @return whether succeed
     */
    boolean goBackWithResult(ScreenResult screenResult);

    /**
     * {@code goBackWithResult} with an animation data.
     *
     * @param screen  page bind data
     * @param screenResult  screen result that will be returned
     * @param animationData animation data for an additional animation configuring
     * @return whether succeed
     */
    boolean goBackWithResult(Screen screen, ScreenResult screenResult, AnimationData animationData);

    /**
     * Goes back to a screen with the given class.
     *
     * @param screenClass screen class for going back
     */
    void goBackTo(Class<? extends Screen> screenClass);

    /**
     * {@code goBackTo} with an animation data.
     *
     * @param screenClass   screen class for going back
     * @param animationData animation data for an additional animation configuring
     */
    void goBackTo(Class<? extends Screen> screenClass, AnimationData animationData);

    /**
     * Goes back to a screen with the given class and returns result to it.
     *
     * @param screenClass  screen class for going back
     * @param screenResult screen result that will be returned
     */
    void goBackToWithResult(Class<? extends Screen> screenClass, ScreenResult screenResult);

    /**
     * {@code goBackToWithResult} with an animation data.
     *
     * @param screenClass   screen class for going back
     * @param screenResult  screen result that will be returned
     * @param animationData animation data for an additional animation configuring
     */
    void goBackToWithResult(Class<? extends Screen> screenClass, ScreenResult screenResult, AnimationData animationData);

    /**
     * Replaces the last screen with a new screen.
     *
     * @param screen new screen
     */
    void replace(Screen screen);

    /**
     * {@code replace} with an animation data.
     *
     * @param screen        new screen
     * @param animationData animation data for an additional animation configuring
     */
    void replace(Screen screen, AnimationData animationData);

    /**
     * Removes all other screens and adds a new screen.
     *
     * @param screen new screen
     */
    void reset(Screen screen);

    /**
     * {@code reset} with an animation data.
     *
     * @param screen        new screen
     * @param animationData animation data for an additional animation configuring
     */
    void reset(Screen screen, AnimationData animationData);

    /**
     * Finishes a current flow or a current top-level screen.
     */
    void finish();

    /**
     * {@code finish} with an animation data.
     *
     * @param screen        screen for back to
     * @param animationData animation data for an additional animation configuring
     */
    void finish(Screen screen, AnimationData animationData);

    /**
     * {@code finish} with an animation data.
     *
     * @param animationData animation data for an additional animation configuring
     */
    void finish(AnimationData animationData);

    /**
     * Finishes a current flow or a current top-level screen and returns a screen result.
     *
     * @param screenResult screen result that will be returned
     */
    void finishWithResult(ScreenResult screenResult);

    /**
     * {@code finishWithResult} with an animation data.
     *
     * @param screenResult  screen result that will be returned
     * @param animationData animation data for an additional animation configuring
     */
    void finishWithResult(ScreenResult screenResult, AnimationData animationData);

    /**
     * Finishes a current top-level screen.
     */
    void finishTopLevel();

    /**
     * {@code finishTopLevel} with an animation data.
     *
     * @param animationData animation data for an additional animation configuring
     */
    void finishTopLevel(AnimationData animationData);

    /**
     * Finishes a current top-level screen and returns a screen result.
     *
     * @param screenResult screen result that will be returned
     */
    void finishTopLevelWithResult(ScreenResult screenResult);

    /**
     * {@code finishTopLevelWithResult} with an animation data.
     *
     * @param screenResult  screen result that will be returned
     * @param animationData animation data for an additional animation configuring
     */
    void finishTopLevelWithResult(ScreenResult screenResult, AnimationData animationData);

    /**
     * Switches screens.
     *
     * @param screen screen for switching to
     */
    void switchTo(Screen screen);

    /**
     * {@code switchTo} with an animation data.
     *
     * @param screen        screen for switching to
     * @param animationData animation data for an additional animation configuring
     */
    void switchTo(Screen screen, AnimationData animationData);

    /**
     * reduce screens.
     *
     * @param screen screen for switching to
     */
    void reduce(Screen screen);

    void reduce(List<Screen> screen);

    /**
     * {@code reduce} with an animation data.
     *
     * @param screen        reduce a   screen
     * @param animationData animation data for an additional animation configuring
     */
    void reduce(List<Screen> screen, AnimationData animationData);


}
